<template>
  <div>
    <!-- 搜索页面头部 -->
    <div class="search-header">
      <!-- 后退按钮 -->
      <van-icon
        name="arrow-left"
        color="white"
        size="0.48rem"
        class="goback"
        @click="$router.back()"
      />
      <!-- 搜索组件 -->
      <!-- 组件内会给原生input标签, 绑定keypress-按键事件
        $emit('search')
      -->
      <van-search
        v-model.trim="kw"
        v-fofo
        placeholder="请输入搜索关键词"
        background="#007BFF"
        shape="round"
        @input="inputFn"
        @search='enter()'
      />
    </div>

        <!-- 搜索历史列表 -->
     <div v-if="kw.length==0">
        <div class="history" >
        <div>搜索历史</div>
        <van-icon name="delete-o" size="0.42667rem"  @click="clearAll"/>
      </div>
       <van-divider />
       <!-- 历史列表   -->
        <div class="history-list">
            <span class="history-item" v-for="(str,index) in historyList" :key="index" @click="historyClick(str)">{{str}}</span>
        </div>
     </div>
        <!-- 搜索联想列表 -->
      <div v-else class="suggestList">
        <div
          class="sugg-item"
          v-for="(str,index) in suggestList"
          :key="index"
          v-html="keywordHightLight(str,kw)"
          @click="suggest(str)"
        ></div>
      </div>

  </div>
</template>

<script>
// 目标1: 跳转到搜索结果页面
// 1. 输入框回车 -> 输入框字  -> 搜索结果页
// 2. 点击联想菜单 -> 点击文字 -> 搜索结果页
// 3. 点击历史记录 -> 点击文字 -> 搜索结果页
// 4. 把历史数据的数组存进本地缓存（不然从search路由跳转到seachResult组件，再跳回去，search组件里的数据就会没了（每一次组件的切换都会被销毁））
// 5. 为什么要在suggest和enter里面添加定时器 因为在watch执行之前，你把kw的值存进historyList，然后路由就马上跳转到searchresult了
// 这时候watch还没有执行呢，所以监听不到historyList(或者会有问题) 所以给路由跳转加一个定时器，保证watch监听到了historyList后再跳转
// 这里涉及到了宏任务和微任务

import { suggestListAPI } from '@/api'
export default {
  name: 'Search',
  data () {
    return {
      kw: '', // 搜索关键字
      timer: null, // 防抖的定时器
      suggestList: [], // 联想列表
      historyList: JSON.parse(sessionStorage.getItem('his')) || [] // 历史数据列表
    }// 为什么后面还要加|| []，因为如果本地缓存中没有值的话，那么historyList: JSON.parse(sessionStorage.getItem('his'))就会报错
    // 所以为了保证本地缓存没有值，也不报错，就赋值为一个空数组
  },
  methods: {
    // 输入框内容实时改变触发的事件
    inputFn () {
      // 防抖:延时执行逻辑代码，事件再次触发时，清除上一个定时器
      clearTimeout(this.timer)
      if (this.kw.length === 0) {
        // 如果输入框里面没有值，清空联想菜单
        this.suggestList = []
      } else {
        this.timer = setTimeout(async () => {
          const res = await suggestListAPI({
            q: this.kw
          })
          this.suggestList = res.data.data.options
        }, 500)
      }
    },
    // 关键字高亮
    keywordHightLight (val, kw) {
      // val是原字符串 kw是搜索关键字
      val = val + ''
      if (val.indexOf(kw) !== -1 && kw !== '') {
        return val.replaceAll(kw, `<span style="color:red;">${kw}</span>`)
      } else {
        return val
      }
    },
    // 输入框回车事件
    enter () {
      if (this.kw.length > 0) {
        // 搜索关键字-保存到历史数据列表数组里
        this.historyList.push(this.kw)
        setTimeout(() => {
          this.$router.push({
            name: 'searchresult',
            params: {
              kw: this.kw
            }
          // path: `/searchresult/${this.kw}`
          // 这两种方法都是params传参 注意，params传参要在路由那里做参数占位
          })
        }, 0)
      }
    },
    // 联想菜单 点击事件
    suggest (str) {
      // 联想菜单关键字-保存到历史数据列表数组里
      this.historyList.push(str)
      setTimeout(() => {
        this.$router.push({
          name: 'searchresult',
          params: {
            kw: str
          }
        })
      })
    },
    // 搜索历史 点击事件
    historyClick (str) {
      this.$router.push({
        name: 'searchresult',
        params: {
          kw: str
        }
        // path: `/searchresult/${this.kw}`
        // 这两种方法都是params传参 注意，params传参要在路由那里做参数占位
      })
    },
    // 清空历史记录
    clearAll () {
      this.historyList = []
    }
  },
  // 监听historyList数组，只要一发生变化，就把数据存进本地缓存
  watch: {
    historyList: {
      immediate: true, // 设置immediate为true后，监听会在被监听值初始化的时候就开始，也就页面上的数据还未变化的时候。
      deep: true, // 因为是数组，所以用深度监听
      handler (newValue, oldValue) {
        // 只要historyList的值改变，就把它存进会话缓存
        const item = Array.from(new Set(this.historyList)) // 数组去重  这种方法的数据去重只能是基本类型,如果是对象的话,他比较的是对象的内存地址
        sessionStorage.setItem('his', JSON.stringify(item))
      }
    }
  }
}
</script>

<style lang='less' scoped>
.search-header {
  height: 46px;
  display: flex;
  align-items: center;
  background-color: #007bff;
  overflow: hidden;
  /*后退按钮*/
  .goback {
    padding-left: 14px;
  }
  /*搜索组件*/
  .van-search {
    flex: 1;
  }
}

  .history {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin: 10px 10px;
  }
  div {
    font-size: 14px;
  }
  .van-divider {
    width: 90%;
    left: 0;
    right: 0;
    margin: 0 auto;
  }
  .suggestList {
    .sugg-item {
      padding: 0 15px;
      border-bottom: 1px solid #f8f8f8;
      font-size: 14px;
      line-height: 50px;
      overflow: hidden;
    }
  }
  .history-list{
      .history-item{
          font-size: 12px;
          display: inline-block;
          padding: 8px 14px;
          background-color: #efefef;
          margin: 10px 8px 8px;
          border-radius: 10px;
      }
  }
</style>
